package com.open.generate.dispatch;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.springframework.core.io.ClassPathResource;

import java.io.*;
import java.nio.file.FileSystems;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;


public class CommonPageParser {
    private static Logger log = LogManager.getLogger(CommonPageParser.class);
    private static VelocityEngine ve;
    private final static String CONTENT_ENCODING = "UTF-8";
    //是否可以替换文件 true =可以替换，false =不可以替换
    private static boolean isReplace = true;

    /**
     * 获取项目的路径
     *
     * @return
     */
    public static String getRootPath() {
        String modulePath = "";
        try {
            File file = new File(CommonPageParser.class.getProtectionDomain().getCodeSource().getLocation().toURI());
            modulePath = file.getParentFile().getParent();
            modulePath = java.net.URLDecoder.decode(modulePath, CONTENT_ENCODING);
            return modulePath;
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return modulePath;
    }

    /**
     * 获取操作系统路径类型
     *
     * @return
     */
    public static String getOsPathType() {
        String osPathType = FileSystems.getDefault().getSeparator();
        if (osPathType.equals("\\")) {
            return "\\\\";
        }
        return "/";
    }

    /**
     * 将.替换为/
     *
     * @param input
     * @return
     */
    public static String convertSlash(String input) {
        if (input == null || input.isEmpty()) {
            return input;
        }
        // 将所有的.替换为/
        String result = input.replace(".", "/");
        // 如果最后一个字符不是/，则添加/
        if (!result.endsWith("/")) {
            result += "/";
        }
        return result;
    }

    static {
        try {
            //获取文件模板根路径
            ClassPathResource resource = new ClassPathResource("template");
            String templateBasePath = resource.getFile().getAbsolutePath();
            log.info("文件模板根路径：" + templateBasePath);
            Properties properties = new Properties();
            properties.setProperty(Velocity.RESOURCE_LOADER, "file");
            properties.setProperty("file.resource.loader.description", "Velocity File Resource Loader");
            properties.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, templateBasePath);
            properties.setProperty(Velocity.FILE_RESOURCE_LOADER_CACHE, "true");
            properties.setProperty("file.resource.loader.modificationCheckInterval", "30");
            properties.setProperty(Velocity.RUNTIME_LOG_LOGSYSTEM_CLASS, "org.apache.velocity.runtime.log.Log4JLogChute");
            properties.setProperty("runtime.log.logsystem.log4j.logger", "org.apache.velocity");
            properties.setProperty("directive.set.null.allowed", "true");
            VelocityEngine velocityEngine = new VelocityEngine();
            velocityEngine.init(properties);
            ve = velocityEngine;
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    /**
     * @param context      内容上下文
     * @param templateName 模板文件路径（相对路径）article\\article_main.html
     * @param @param       fileDirPath
     * @param @param       targetFile 生成页面文件路径（相对路径） vowo\index_1.html
     * @return void
     * @throws
     */
    public static void WriterPage(VelocityContext context, String templateName, String fileDirPath, String targetFile) {
        try {
            File file = new File(fileDirPath + targetFile);
            if (!file.exists()) {
                // 创建指定路径中的所有目录
                new File(file.getParent()).mkdirs();
            } else {
                if (isReplace) {
                    log.info("替换文件" + file.getAbsolutePath());
                } else {
                    log.info("生成失败" + file.getAbsolutePath() + "文件已存在");
                    return;
                }
            }
            Template template = ve.getTemplate(templateName, CONTENT_ENCODING);
            FileOutputStream fos = new FileOutputStream(file);
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos, CONTENT_ENCODING));
            template.merge(context, writer);
            writer.flush();
            writer.close();
            fos.close();
            log.info("生成成功" + file.getAbsolutePath());
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    /**
     * 文件后面追加内容
     *
     * @param context      内容
     * @param templateName 模板文件路径（相对路径）article\\article_main.html
     * @param fileDirPath  文件路径
     * @param targetFile   文件名
     */
    public static void writerConfig(VelocityContext context, String templateName, String fileDirPath, String targetFile) {
        try {
            File file = new File(fileDirPath + targetFile);
            if (!file.exists()) {
                new File(file.getParent()).mkdirs();
            }
            Template template = ve.getTemplate(templateName, CONTENT_ENCODING);
            FileOutputStream fos = new FileOutputStream(file, true);
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos, CONTENT_ENCODING));
            template.merge(context, writer);
            writer.flush();
            writer.close();
            fos.close();
            log.info("生成成功" + file.getAbsolutePath());
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    /**
     * 向Zip中添加文件
     *
     * @param context  内容
     * @param zipOut   ZIP输出流
     * @param fileName 模板文件名
     * @param filePath ZIP文件中的路径
     */
    public static void WriterPageZip(VelocityContext context, ZipOutputStream zipOut, String fileName, String filePath) {
        try {
            // 使用Velocity模板生成文件内容
            Template template = ve.getTemplate(fileName, CONTENT_ENCODING);
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(byteArrayOutputStream, CONTENT_ENCODING))) {
                template.merge(context, writer);
                writer.flush();
            }

            // 将生成的内容添加到ZIP中
            try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray())) {
                ZipEntry zipEntry = new ZipEntry(filePath);
                zipOut.putNextEntry(zipEntry);

                byte[] bytes = new byte[1024];
                int length;
                while ((length = byteArrayInputStream.read(bytes)) >= 0) {
                    zipOut.write(bytes, 0, length);
                }
                zipOut.closeEntry();
            }

        } catch (Exception e) {
            log.error("向Zip添加模板文件失败, context: {}", context, e);
        }
    }
}